package com.example.ndktest;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import com.example.ndktest.PcmWriter.rawData;

import android.util.Log;

public class Encoder implements Runnable {

	private volatile int leftSize = 0;
	private final Object mutex = new Object();
	private Speex speex = new Speex();
	private long ts;
	private Consumer consumer;
	private byte[] processedData = new byte[1024];
	private short[] rawdata = new short[4096];
	private volatile boolean isRecording;
	private static final String LOG_TAG_Encoder = "LOG_TAG_Encoder";
	private SpxWriter spxWriter;
	private PcmWriter pcmWriter;
	private List<rawData> list;
	
	public Encoder(Consumer consumer) {
		super();
		this.consumer = consumer;
		speex.init();
		
		list = Collections.synchronizedList(new LinkedList<rawData>());
	}

	public void run() {

		android.os.Process
				.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);

		int getSize = 0;
		//bushcat for test only
		//spxWriter = new SpxWriter("/android_encoded.Spx");
		//spxWriter.init();
		//spxWriter.setRecording(true);
		//Thread spxWriterThread = new Thread(spxWriter);
		//spxWriterThread.start();
		//
		//pcmWriter = new PcmWriter("/android_decoded.pcm");
		//pcmWriter.init();
		//pcmWriter.setRecording(true);
		//Thread pcmWriterThread = new Thread(pcmWriter);
		//pcmWriterThread.start();
		
		while (this.isRecording()) {
			if (isIdleNew()) {
				try {
					Thread.sleep(20);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				continue;
			}
			//synchronized (mutex) {
				while(list.size() > 0)
				{
					rawData tempData = list.remove(0);
					getSize = speex.encode(tempData.data, 0, processedData, tempData.size);
					MainActivity.fileLoger.putData("tempData.size = " + tempData.size + "encodedSize = " + getSize + "\r\n");
					{
						// for test only
						short testData[] = new short[1024];
						int decodedLen = speex.decode(processedData, testData, getSize);
						//pcmWriter.putData(testData, decodedLen);
						//Log.i(LOG_TAG_Encoder, "encoded, size="+getSize);
						//MainActivity.fileLoger.putData("decodedLen = " + decodedLen + "\r\n");
					}
					setIdle();
					if (getSize > 0) {
						consumer.putData(ts, processedData, getSize);
						MainActivity.fileLoger.putData("putData to send, size = " + getSize + "\r\n");
					}
				}
			//}
		}
	}

	public void putData(long ts, short[] data, int size) {
		synchronized (mutex) {
			this.ts = ts;
			System.arraycopy(data, 0, rawdata, 0, size);
			this.leftSize = size;
		}
	}
	
	public void putDataNew(short[] data, int size){
		int iLoop = size / Configuration.ENCODER_FRAME_SIZE;
		int iLeft = size % Configuration.ENCODER_FRAME_SIZE;
		int iCopiedLen = 0;
		
		for(int i=0; i<iLoop; i++)
		{
			rawData tempData = new rawData();
			
			tempData.size = Configuration.ENCODER_FRAME_SIZE;
			System.arraycopy(data, iCopiedLen, tempData.data, 0, Configuration.ENCODER_FRAME_SIZE);
			iCopiedLen += Configuration.ENCODER_FRAME_SIZE;
			list.add(tempData);
		}
		
		if(iLeft != 0)
		{
			rawData tempData = new rawData();
			
			tempData.size = iLeft;
			System.arraycopy(data, iCopiedLen, tempData.data, 0, iLeft);
			list.add(tempData);
		}
	}

	public boolean isIdle() {
		synchronized (mutex) {
			return leftSize == 0 ? true : false;
		}
	}
	
	public boolean isIdleNew()
	{
		synchronized(mutex){
			return list.size() == 0 ? true : false;
		}
	}

	public void setIdle() {
		leftSize = 0;
	}

	public void setRecording(boolean isRecording) {
		synchronized (mutex) {
			this.isRecording = isRecording;
			if(spxWriter != null)
			{
				spxWriter.setRecording(isRecording);
			}
			if(pcmWriter != null)
			{
				pcmWriter.setRecording(isRecording);
			}
		}
	}

	public boolean isRecording() {
		synchronized (mutex) {
			return isRecording;
		}
	}
	
	class rawData {
		int size;
		short[] data = new short[Configuration.ENCODER_FRAME_SIZE];
	}
}
